using CriWare;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;

namespace IQIGame.Onigao.Game
{
    /// <summary>
    /// 音频播放监听回调，或者控制播放中的音频
    /// </summary>
    public class AudioPlayback : IReusableClass
    {
        public bool isInit { private set; get; }
        public CriAtomSource source { get; private set; }

        private CriAtomExPlayback _exPlayback;

        public CriAtomExPlayback.Status status => _exPlayback.status;

        public bool isRemoved => !isInit || status == CriAtomExPlayback.Status.Removed;

        public uint MaxStore => 30;

        private AutoResetUniTaskCompletionSource _unitaskCompletionSource;

        public void Initialize(CriAtomExPlayback playback, CriAtomSource source)
        {
            _exPlayback = playback;
            this.source = source;
            this.isInit = true;
        }

        /// <summary>
        /// UniTask 等待音频播放完成
        /// </summary>
        /// <returns></returns>
        public UniTask ToUniTask()
        {
            if (_unitaskCompletionSource != null)
            {
                return _unitaskCompletionSource.Task;
            }
            _unitaskCompletionSource = AutoResetUniTaskCompletionSource.Create();
            return _unitaskCompletionSource.Task;
        }

        public void OnReset()
        {
            this.isInit = false;
            source = null;
            _exPlayback = default;
            if (_unitaskCompletionSource != null)
            {
                // 注意！这里要先置空，再调用，TrySetResult会先调用await之后的代码，如果await之后有给TaskSource赋新值，然后这里再置空，那么_completeActTaskSource就永远为null了。
                // 若置空不及时导致了多次source.TrySetResult，会导致池内数据异常
                var rSource = _unitaskCompletionSource;
                _unitaskCompletionSource = null;
                rSource.TrySetCanceled();
            }
        }

        public long GetPlayedTime()
        {
            if (!isInit)
            {
                return 0;
            }
            return _exPlayback.GetTime();
        }

        public void Pause(bool sw)
        {
            if (!isInit)
            {
                return;
            }
            this._exPlayback.Pause(sw);
        }

        public void Stop()
        {
            if (!isInit)
            {
                return;
            }
            this._exPlayback.Stop();
            if (_unitaskCompletionSource != null)
            {
                _unitaskCompletionSource.TrySetCanceled();
                _unitaskCompletionSource = null;
            }
        }

        public void InvokeComplete()
        {
            if (_unitaskCompletionSource != null)
            {
                _unitaskCompletionSource.TrySetResult();
                _unitaskCompletionSource = null;
            }
        }
    }

}
